package com.opencloud.iot.provider.controller;

import cn.hutool.core.date.DateUtil;
import com.opencloud.common.model.ResultBody;
import com.opencloud.iot.client.model.entity.*;
import com.opencloud.iot.provider.service.*;
import com.opencloud.iot.provider.service.feign.YwtRemoteService;
import com.opencloud.ywt.client.model.entity.BhyfStudent;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.hamcrest.core.IsNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 物联网设备 信息统计
 *
 * @author yeyong
 */
@Slf4j
@RestController
@Api(value = "物联网设备", tags = "物联网设备 信息统计")
public class IotDaySleepResultController {
    @Autowired
    private IotDaySleepResultService iotDaySleepResultService;

    @Autowired
    private IotNStrengService iotNStrengService;

    @Autowired
    private YwtRemoteService ywtRemoteService;

    @Autowired
    private IotTaskService iotTaskService;

    @Autowired
    private IotTaskRunService iotTaskRunService;

    @ApiOperation(value = "获取学生列表", notes = "获取学生列表")
    @GetMapping(value = "/iot/getstudentlist")
    public List<BhyfStudent> getstudentlist(
            @RequestParam(value = "gid", required = false) Integer gid,
            @RequestParam(value = "classid", required = false) Integer classid
    )
    {
        return ywtRemoteService.getBhyfStudentList(gid,classid);
    }

    /**
     * 获取日睡眠统计信息
     *
     * @param watchmac
     * @param slpstatus
     * @param thisdate
     * @return
     */
    @ApiOperation(value = "获取日睡眠统计信息", notes = "获取日睡眠统计信息")
    @GetMapping(value = "/iot/daysleeplist")
    public List<IotDaySleepResult> getIotDaySleepResult(
            @RequestParam(value = "watchmac", required = false) String watchmac,
            @RequestParam(value = "slpstatus", required = false) Integer slpstatus,
            @RequestParam(value = "thisdate", required = false) String thisdate
    ) {
        return iotDaySleepResultService.findListPage(watchmac, slpstatus, thisdate);
    }

    /**
     * 创建日睡眠统计信息
     *
     * @param watchmac
     * @param thisDate
     * @return
     */
    @ApiOperation(value = "创建日睡眠统计信息", notes = "创建日睡眠统计信息")
    @GetMapping(value = "/iot/daysleepcreate")
    public ResultBody<Integer> CreateIotDaySleepResult(String watchmac, String thisDate,String isTest) {
        //执行任务
        //如果是自定义手环和时间 则只处理这一个watch和date的
        if(isTest==null) {
            log.error("生成当日的数据");
            //去任务表task查找需要执行该任务tasktype=1的园所
            List<IotTask> iotTaskList = iotTaskService.findTaskByType(1);
            for (int i = 0; i < iotTaskList.size(); i++) {
                List<BhyfStudent> students = ywtRemoteService.getBhyfStudentList(iotTaskList.get(i).getGid(), 0);
                MyThread myThread = new MyThread(iotTaskList.get(i), students);
                myThread.start();
            }
        } else if (isTest.equals("a")) {
            log.error("生成指定日期和指定手环的数据");
            BhyfStudent student = new BhyfStudent();
            student.setMac(watchmac);
            IotDaySleepResult model = CreateIotRecord(student,thisDate);
            IotDaySleepResult mmm = DoCreate(model);
            return ResultBody.ok().data(mmm.getId());
        } else if(isTest.equals("b")) {
            //去任务表task查找需要执行该任务tasktype=1的园所
            log.error("生成指定日期的数据");
            List<IotTask> iotTaskList = iotTaskService.findTaskByType(1);
            for (int i = 0; i < iotTaskList.size(); i++) {
                IotTask t = iotTaskList.get(i);
                List<BhyfStudent> students = ywtRemoteService.getBhyfStudentList(t.getGid(), 0);
                for(int j=0;j<students.size();j++){
                    IotDaySleepResult sleepResult = CreateIotRecord(students.get(j),thisDate);
                    DoCreate(sleepResult);
                }
            }
        }
        return ResultBody.ok().data(0);
    }

    public class MyThread extends Thread {
        IotTask t = new IotTask();//定义线程内变量
        List<BhyfStudent> s = new ArrayList<>();
        public MyThread(IotTask t,List<BhyfStudent> s) {
            //定义带参数的构造函数,达到初始化线程内变量的值
            this.t = t;
            this.s = s;
        }
        @Override
        public void run() {
            System.out.println("当前执行线程的园:" + t.getGname());
            //生成新的任务执行
            Date dt1 = new Date();
            String startTime = DateUtil.formatDate(dt1)+" "+t.getStarttime().toString()+":00";
            String endTime = DateUtil.formatDate(dt1)+" "+t.getEndtime().toString()+":00";
            Date dtS = DateUtil.parseDateTime(startTime);
            Date dtE = DateUtil.parseDateTime(endTime);

            if (dt1.getTime() < dtS.getTime() || dt1.getTime() > dtE.getTime()) {
                //超出任务指定的时间点
                log.error("超出任务指定的时间点");
            } else {
                IotTaskRun entiy = new IotTaskRun();
                entiy.setCreatetime(new Date());
                entiy.setTaskid(t.getId());
                entiy.setThisdate(new Date());
                entiy.setException("");
                //开始执行任务

                int j =0;
                for (int i=0;i<s.size();i++)
                {
                    BhyfStudent ss = s.get(i);
                    IotDaySleepResult sleepResult = CreateIotRecord(ss,DateUtil.format(dt1, "yyyy-MM-dd"));
                    DoCreate(sleepResult);
                    log.error("当前学生:"+ss.getMac()+" 姓名："+ss.getStudentname());
                    if(sleepResult!=null){j++;}
                }
                entiy.setResult("任务执行结束 学生数量："+s.size()+" 执行数量:"+j);
                entiy.setStatus(1);
                iotTaskRunService.AddTaskRun(entiy);
                log.error("任务执行结束 学生数量："+s.size()+" 执行数量:"+j);
            }
        }
    }

    public IotDaySleepResult CreateIotRecord(BhyfStudent student,String thisDate){
        IotDaySleepResult entiy = new IotDaySleepResult();
        List<IotDaySleepResult> iotDaySleepResults = iotDaySleepResultService.findListPage(student.getMac(), -1, thisDate);
        if(iotDaySleepResults.size()<=0) {
            //log.error("没数据 新增");
            entiy.setSleepresult("");
            entiy.setCreatetime(new Date());
            entiy.setSlpstatus(5);
            entiy.setIsbreak(0);
            entiy.setWatchmac(student.getMac());
            entiy.setThisdate(DateUtil.parseDate(thisDate));
            entiy.setWatchstatus(1);
            entiy.setIntime(null);
            entiy.setSleeptime(0.0);
            entiy.setOuttime(null);
            iotDaySleepResultService.addIotDaySleepResult(entiy);
        }
        List<IotDaySleepResult> newIot = iotDaySleepResultService.findListPage(student.getMac(), -1, thisDate);
        if(newIot.size()>0) {
            //log.error("有数据");
            entiy = newIot.get(0);
        }
        return entiy;
    }

    public IotDaySleepResult DoCreate(IotDaySleepResult entiy) {
        if(entiy.getWatchmac()!=null && !entiy.getWatchmac().isEmpty()) {
            Long sleepStartTime = DateUtil.parse(DateUtil.format(entiy.getThisdate(),"yyyy-MM-dd") + " 08:30:00", "yyyy-MM-dd HH:mm:ss").getTime() / 1000;
            Long sleepEndTime = DateUtil.parse(DateUtil.format(entiy.getThisdate(),"yyyy-MM-dd") + " 16:30:00", "yyyy-MM-dd HH:mm:ss").getTime() / 1000;
            //2、查询当日该手环是否有数据

            //5、按规则计算
            List<IotNStreng> nStrengs = new ArrayList<>();
            nStrengs = iotNStrengService.findList(sleepStartTime + 28800, sleepEndTime + 28800, entiy.getWatchmac());
            //是否佩戴规则-大于5的300条以上
            if (nStrengs != null && !nStrengs.isEmpty()) {
                if (nStrengs.stream().filter((IotNStreng iots) -> iots.getAngle() > 10).collect(Collectors.toList()).size() >= 1) {
                    entiy.setWatchstatus(1);
                } else {
                    entiy.setWatchstatus(0);
                }
            } else {
                entiy.setWatchstatus(0);
            }
            //入睡点规则-连续50条<=7的第一个点
            Long StartSleepTime = DateUtil.parse(DateUtil.format(entiy.getThisdate(),"yyyy-MM-dd") + " 12:00:00", "yyyy-MM-dd HH:mm:ss").getTime() / 1000;
            Long EndSleepTime = DateUtil.parse(DateUtil.format(entiy.getThisdate(),"yyyy-MM-dd") + " 15:00:00", "yyyy-MM-dd HH:mm:ss").getTime() / 1000;
            List<IotNStreng> nStrengsSleep = nStrengs.stream().filter((IotNStreng iots) -> iots.getTimestamp() >= (StartSleepTime + 28800) && iots.getTimestamp() <= (EndSleepTime + 28800)).collect(Collectors.toList());
            List<TodaySleepInfo> sleepInfos = getPoint(7, nStrengsSleep);
            if (sleepInfos != null) {
                //计算各种数据
                int breakcount = 0;
                double times = 0.0;
                int status = 3;
                long intime = 0;
                long outtime = 0;
                //-----循环睡眠数据-----
                for (int j = 0; j < sleepInfos.size(); j++) {
                    long sleeptime = 0;
                    long waketime = 0;
                    TodaySleepInfo t = sleepInfos.get(j);
                    if (t.sleepPoint != null) {
                        if (t.sleepPoint.nStreng != null) {
                            sleeptime = t.sleepPoint.nStreng.getTimestamp();
                            if (j == 0) {
                                intime = sleeptime;
                            }
                        }
                    }
                    if (t.wakePoint != null) {
                        if (t.wakePoint.nStreng != null) {
                            waketime = t.wakePoint.nStreng.getTimestamp();
                            outtime = waketime;
                        }
                    }
                    if (waketime == 0) {
                        waketime = new Date().getTime() / 1000;
                    }
                    if (sleeptime == 0) {
                        times = times + 0;
                    } else {
                        if (waketime > 0) {
                            times = times + (waketime - sleeptime) / 60;
                        }
                    }
                    if (sleeptime > 0) {
                        final long sss = sleeptime;
                        final long www = waketime;
                        List<IotNStreng> nnn = nStrengsSleep.stream().filter(iotNStreng -> iotNStreng.getTimestamp() >= sss && iotNStreng.getTimestamp() <= www).collect(Collectors.toList());
                        breakcount = breakcount + nnn.stream().filter(iotNStreng -> iotNStreng.getAngle() >= 7).collect(Collectors.toList()).size();
                    }
                }
                //-----循环结束-----
                if (sleepInfos.size() >= 2) {
                    entiy.setSleepresult("是");
                } else {
                    entiy.setSleepresult("否");
                }
                if (intime == 0) {
                    entiy.setIntime(null);
                } else {
                    entiy.setIntime(new Date((intime - 28800) * 1000));
                }
                if (outtime == 0) {
                    entiy.setOuttime(null);
                } else {
                    entiy.setOuttime(new Date((outtime - 28800) * 1000));
                }
                entiy.setIsbreak(breakcount);
                entiy.setSleeptime(times);
                if (times <= 60) {
                    status = 2;
                } else if (sleepInfos.size() == 0) {
                    status = 1;
                } else if (nStrengsSleep.size() == 0) {
                    status = 0;
                }
                entiy.setSlpstatus(status);
                entiy.setUpdatetime(new Date());
                //3、有数据 更新 //4、无数据 插入
                iotDaySleepResultService.updateIotDaySleepResult(entiy);
            }
            return entiy;
        }else{
            return new IotDaySleepResult();
        }
    }


    private class TodaySleepInfo {
        public TodayPoint sleepPoint;
        public TodayPoint wakePoint;

        public void setSleepPoint(TodayPoint sleepPoint) {
            this.sleepPoint = sleepPoint;
        }

        public TodayPoint getSleepPoint() {
            return sleepPoint;
        }

        public void setWakePoint(TodayPoint wakePoint) {
            this.wakePoint = wakePoint;
        }

        public TodayPoint getWakePoint() {
            return wakePoint;
        }
    }

    private class TodayPoint {
        public IotNStreng nStreng;
        public Integer index;
        public Integer status;

        public void setnStreng(IotNStreng nStreng) {
            this.nStreng = nStreng;
        }

        public IotNStreng getnStreng() {
            return nStreng;
        }

        public void setIndex(Integer index) {
            this.index = index;
        }

        public Integer getIndex() {
            return index;
        }

        public void setStatus(Integer status) {
            this.status = status;
        }

        public Integer getStatus() {
            return status;
        }
    }

    private List<TodaySleepInfo> getPoint(int CompareV, List<IotNStreng> list) {
        List<TodayPoint> sleepPoints = new ArrayList<>();
        List<TodayPoint> wakePoints = new ArrayList<>();
        //按标准分组
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getAngle() <= CompareV) {
                TodayPoint sp = new TodayPoint();
                sp.status = 1;
                sp.index = i;
                sp.nStreng = list.get(i);
                sleepPoints.add(sp);
            } else {
                TodayPoint sp = new TodayPoint();
                sp.status = 2;
                sp.index = i;
                sp.nStreng = list.get(i);
                wakePoints.add(sp);
            }
        }
        //遍历睡眠列表和醒来列表
        List<TodaySleepInfo> returnList = GetTheSleepPoint(sleepPoints, wakePoints, 50, 3);
        return returnList;
    }

    private List<TodaySleepInfo> GetTheSleepPoint(List<TodayPoint> sleeplist, List<TodayPoint> wakelist, Integer sc, Integer wc) {
        List<TodaySleepInfo> returnInfo = new ArrayList<>();
        List<TodayPoint> subList = new ArrayList<>();
        int j = 0;
        TodayPoint wake = new TodayPoint();
        wake.setIndex(0);
        for (int i = 0; i < sleeplist.size(); i++) {
            TodayPoint tmpv = sleeplist.get(i);
            if(wake!=null && tmpv!=null) {
                if (wake.getIndex() > tmpv.getIndex()) {
                    continue;
                } else {
                    if (subList != null && subList.size() > 0) {
                        TodayPoint p = subList.get(subList.size() - 1);
                        if(p!=null) {
                            if (tmpv.getIndex() - p.getIndex() == 1) {
                                subList.add(tmpv);
                                j += 1;
                            } else {
                                if (j >= sc) {
                                    TodaySleepInfo sleepInfo = new TodaySleepInfo();
                                    sleepInfo.setSleepPoint(subList.get(0));
                                    //开始找醒来点
                                    if (wakelist.size() > 0) {
                                        TodayPoint lastwake = wakelist.get(wakelist.size() - 1);
                                        if (lastwake.getIndex() > tmpv.getIndex()) {
                                            wakelist = wakelist.stream().filter(www -> www.getIndex() >= tmpv.getIndex()).collect(Collectors.toList());
                                            TodayPoint wakepoint = GetTheWakePoint(wakelist, wc);
                                            if (wakepoint != null) {
                                                sleepInfo.setWakePoint(wakepoint);
                                                wake.setIndex(wakepoint.getIndex());
                                                wake.setStatus(wakepoint.getStatus());
                                                wake.setnStreng(wakepoint.getnStreng());
                                            }
                                        }
                                    }
                                    returnInfo.add(sleepInfo);
                                    subList.clear();
                                    j = 0;
                                } else {
                                    subList.clear();
                                    j = 0;
                                    subList.add(tmpv);
                                }
                            }
                        }
                    } else {
                        j += 1;
                        subList.add(tmpv);
                    }
                }
            }
        }
        return returnInfo;
    }

    private TodayPoint GetTheWakePoint(List<TodayPoint> wakelist, Integer wc) {
        TodayPoint returnPoint = new TodayPoint();
        returnPoint.setIndex(0);
        List<TodayPoint> subList = new ArrayList<>();
        int j = 0;
        for (int i = 0; i < wakelist.size(); i++) {
            TodayPoint tmpv = wakelist.get(i);
            if (subList != null && subList.size()>0) {
                TodayPoint p = subList.get(subList.size() - 1);
                if (tmpv.getIndex() - p.getIndex() == 1) {
                    subList.add(tmpv);
                    j += 1;
                    if (j >= wc) {
                        returnPoint = subList.get(0);
                        return returnPoint;
                    }
                } else {
                    subList.clear();
                    subList.add(tmpv);
                }
            } else {
                j += 1;
                subList.add(tmpv);
            }
        }
        return returnPoint;
    }
}
